package cn.com.pc.content.service;

import cn.com.pc.content.constant.LogConstants;
import cn.com.pc.content.domain.log.FrontendLog;
import cn.com.pc.content.domain.log.OperationLog;
import cn.com.pc.content.dto.FrontendLogForm;
import cn.com.pc.content.dto.OperationLogForm;
import cn.com.pc.content.dto.PageResult;
import cn.com.pc.content.dto.Sort;
import cn.com.pc.content.service.es.ESCurdService;
import cn.com.pc.content.service.es.ESQueryService;
import cn.com.pc.content.util.ElasticUtil;
import cn.com.pc.content.util.LocalDateUtils;
import lombok.SneakyThrows;
import org.bson.types.ObjectId;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ResponseStatusException;

@Service
public class LogService {

    @Autowired
    private ESCurdService esCurdService;

    @Autowired
    private ESQueryService esQueryService;

    public PageResult<?> listOperationLogsByForm(OperationLogForm operationLogForm, Sort sort) {
        // 过滤
        BoolQueryBuilder boolQueryBuilder = operationLogQueryFilter(operationLogForm);
        // 排序
        SortBuilder<?> sortBuilder = operationLogSortBuilder(sort);
        // 分页
        SearchSourceBuilder searchSourceBuilder = ElasticUtil.initSearchSourceBuilder(boolQueryBuilder, sortBuilder, (operationLogForm.getPageNum() - 1) * operationLogForm.getPageSize(), operationLogForm.getPageSize(), 60, true);
        // 执行搜索
        return esQueryService.search(searchSourceBuilder, OperationLog.class, operationLogForm.getPageNum(), operationLogForm.getPageSize(), LogConstants.OPERATION_LOG_IDX);
    }

    public BoolQueryBuilder operationLogQueryFilter(OperationLogForm operationLogForm) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (StringUtils.hasLength(operationLogForm.getId())) {
            queryBuilder = queryBuilder.must(QueryBuilders.termsQuery("id", operationLogForm.getId()));
        }
        if (operationLogForm.getUserId() != null) {
            queryBuilder = queryBuilder.must(QueryBuilders.termQuery("userId", operationLogForm.getUserId()));
        }
        if (StringUtils.hasLength(operationLogForm.getUserName())) {
            queryBuilder = queryBuilder.must(QueryBuilders.matchQuery("userName", operationLogForm.getUserName()));
        }
        if (operationLogForm.getMinLogAt() != null) {
            queryBuilder = queryBuilder.must(QueryBuilders.rangeQuery("logAt").gte(LocalDateUtils.format(operationLogForm.getMinLogAt())));
        }
        if (operationLogForm.getMaxLogAt() != null) {
            queryBuilder = queryBuilder.must(QueryBuilders.rangeQuery("logAt").lte(LocalDateUtils.format(operationLogForm.getMaxLogAt())));
        }
        if (StringUtils.hasLength(operationLogForm.getUri())) {
            queryBuilder = queryBuilder.must(QueryBuilders.matchQuery("uri", operationLogForm.getUri()));
        }
        if (StringUtils.hasLength(operationLogForm.getMethod())) {
            queryBuilder = queryBuilder.must(QueryBuilders.termQuery("method", operationLogForm.getMethod()));
        }
        if (StringUtils.hasLength(operationLogForm.getOperation())) {
            queryBuilder = queryBuilder.must(QueryBuilders.matchQuery("operation.iks", operationLogForm.getOperation()));
        }
        return queryBuilder;
    }

    public SortBuilder<?> operationLogSortBuilder(Sort sort) {
        SortBuilder<?> sortBuilder;
        String sortBy = sort.getSortBy();
        if (StringUtils.hasLength(sortBy)) {
            sortBuilder = SortBuilders.fieldSort(sortBy);
        } else {
            // 评分排序
            sortBuilder = SortBuilders.scoreSort();
        }
        sortBuilder.order(sort.getSortOrder());
        return sortBuilder;
    }

    @SneakyThrows
    public String saveFrontendLog(FrontendLog frontendLog) {
        frontendLog.setId(new ObjectId().toString());
        RestStatus status = esCurdService.insert(LogConstants.FRONTEND_LOG_IDX, FrontendLog.class.toString(), frontendLog);
        if (status.getStatus() == RestStatus.CREATED.getStatus()) {
            return frontendLog.getId();
        } else {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "前端日志写入失败");
        }
    }

    public PageResult<?> listFrontendLogsByForm(FrontendLogForm frontendLogForm, Sort sort) {
        // 过滤
        BoolQueryBuilder boolQueryBuilder = FrontendLogQueryFilter(frontendLogForm);
        // 排序
        SortBuilder<?> sortBuilder = operationLogSortBuilder(sort);
        // 分页
        SearchSourceBuilder searchSourceBuilder = ElasticUtil.initSearchSourceBuilder(boolQueryBuilder, sortBuilder, (frontendLogForm.getPageNum() - 1) * frontendLogForm.getPageSize(), frontendLogForm.getPageSize(), 60, true);
        // 执行搜索
        return esQueryService.search(searchSourceBuilder, FrontendLog.class, frontendLogForm.getPageNum(), frontendLogForm.getPageSize(), LogConstants.FRONTEND_LOG_IDX);
    }

    public BoolQueryBuilder FrontendLogQueryFilter(FrontendLogForm frontendLogForm) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (StringUtils.hasLength(frontendLogForm.getId())) {
            queryBuilder = queryBuilder.must(QueryBuilders.termsQuery("id", frontendLogForm.getId()));
        }
        if (frontendLogForm.getUserId() != null) {
            queryBuilder = queryBuilder.must(QueryBuilders.termQuery("userId", frontendLogForm.getUserId()));
        }
        if (StringUtils.hasLength(frontendLogForm.getUserName())) {
            queryBuilder = queryBuilder.must(QueryBuilders.matchQuery("userName", frontendLogForm.getUserName()));
        }
        if (frontendLogForm.getMinLogAt() != null) {
            queryBuilder = queryBuilder.must(QueryBuilders.rangeQuery("logAt").gte(LocalDateUtils.format(frontendLogForm.getMinLogAt())));
        }
        if (frontendLogForm.getMaxLogAt() != null) {
            queryBuilder = queryBuilder.must(QueryBuilders.rangeQuery("logAt").lte(LocalDateUtils.format(frontendLogForm.getMaxLogAt())));
        }
        if (StringUtils.hasLength(frontendLogForm.getUri())) {
            queryBuilder = queryBuilder.must(QueryBuilders.matchQuery("uri", frontendLogForm.getUri()));
        }
        if (StringUtils.hasLength(frontendLogForm.getMethod())) {
            queryBuilder = queryBuilder.must(QueryBuilders.termQuery("method", frontendLogForm.getMethod()));
        }
        if (StringUtils.hasLength(frontendLogForm.getDetail())) {
            queryBuilder = queryBuilder.must(QueryBuilders.matchQuery("detail.iks", frontendLogForm.getDetail()));
        }
        return queryBuilder;
    }
}

